-- Author: shunguo.chen
-- Date: 2016-06-17 11:42:45
--
-- IMRecordController 管理录音／播放录音
--

local fileName = string.getModeName(...)
local ClassRef = class(fileName, app.mvc.ControllerBase)

local RECORD_DURATION_MAX = 20
local RECORD_COUNTDOWN = 5 --录音倒计时长度

function ClassRef:ctor(params)
	self.super.ctor(self, params)

end

function ClassRef:init()
	self._model = app:getInst("IMModel")

	self._recordNode = nil
	self._recordStopNode = nil
	self._recordPhase = Enums.IMRecordPhase.End

	self._recordChannel = nil
	self._recordEndCb = nil

	self._filePath = nil
	self._recordStartTime = 0

	self._voiceBtn = nil

	-- real time
	self._roomId = nil
	self._memberId = nil

	self._hasMic = false
	self._hasSpeaker = false
end

function ClassRef:listEvent()
    return {
    	"onRecordPhaseChange",
    	"onBattleSceenCapture"
	}
end

function ClassRef:onEvent(eventName, ...)
	if eventName == "onBattleSceenCapture" then
		if ... then
			self:_hideRecordNodes()
		end
	elseif eventName == "onRecordPhaseChange" then
		self:_setRecordPhase(...)
	end
end

function ClassRef:_setVoiceBtn(btn)
	if self._voiceBtn and not tolua.isnull(self._voiceBtn) then
		if self._voiceBtn.setIsInPlay then
			self._voiceBtn:setIsInPlay(false)
		end
		if self._voiceBtn.stopPlay then
			self._voiceBtn:stopPlay()
		end
	end
	self._voiceBtn = btn
end

function ClassRef:playAudio(btn)
	local data = btn:getData()
	assert(data ~= nil, "IMRecordController.playAudio data can't be nil")

	local path = data.audioPath
	assert(path ~= nil, "IMRecordController.playAudio path can't be nil")

	-- print("===>IMAPI IMRecordController.playAudio", path)

	self._model:setModeTranslate()
	local code = im.playAudio(path)
	if code == 0 then
		self:_setVoiceBtn(btn)
		self._voiceBtn:setIsInPlay(true)
		self._voiceBtn:play()

		-- AM.pauseAll()
		im.isPlaying = true
	else
		self:stopPlay()
	end
end

function ClassRef:stopPlay()
	self._model:setModeTranslate()
	im.stopPlay()
	im.isPlaying = false
	-- AM.resumeAll()
	self:_setVoiceBtn(nil)
	self:_autuPlayAudio()
end

function ClassRef:_autuPlayAudio()
	app:sendMsg("IMRoomController", "autoPlayAudio")
end

function ClassRef:startRecord()
	-- 添加定时器
	self:removeScheduler()
	self._cronsIdx = scheduler.newCron(handler(self, self._tick), 1, true)
	self:_tick()

	self._model:setModeTranslate()
	self._filePath = self._model:getRecordPath()
	local code = im.startRecord(self._filePath)
	-- print("===>IMAPI im.startRecord code", code, self._filePath)
	if code == 0 then
		self:_setRecordPhase(Enums.IMRecordPhase.Record)
	else
		if code == 12292 then
			self._model:applyMessageKey()
		end

		display.pushToast(L("tips_1150009"))
		
		self:_setRecordPhase(Enums.IMRecordPhase.End)
		self:recordEnd()
	end
end

function ClassRef:recordEnd(fileId, filePath, duration)
	-- print("===>IMAPI im.stopRecord", fileId, filePath, duration)
	executeFunc(self._recordEndCb, fileId, filePath, duration)
	self._recordEndCb = nil
	self._recordChannel = nil

	self:needBackToRealtime()
	self:_autuPlayAudio()
end

function ClassRef:stopRecord(duration)
	-- print("===>IMAPI im.stopRecord recordChannel duration", self._recordChannel, duration)

	self._model:setModeTranslate()
	local code = im.stopRecord()
	-- print("===>IMAPI im.stopRecord code", code)
	if duration and code == 0 then
		if self._recordChannel then
			self._model:onRecordSucc(self._recordChannel, self._filePath, duration)
		else
			self._model:uploadAudio(self._filePath, function(filePath, fileId)
					-- print("===>IMAPI uploadAudio cb", filePath, fileId)
					self:recordEnd(fileId, filePath, duration)
				end)
		end
	else
		self:recordEnd()
	end
	-- 移除定时器
	self:removeScheduler()
end

function ClassRef:hasMicOrSpeaker()
	return self._roomId ~= nil and (self._hasMic or self._hasSpeaker)
end

function ClassRef:hasMic()
	return self._roomId ~= nil and self._hasMic
end

function ClassRef:hasSpeaker()
	return self._roomId ~= nil and self._hasSpeaker
end

function ClassRef:getMicSpeaker()
	-- print("===>IMAPI IMRecordController.getMicSpeaker", self._hasMic, self._hasSpeaker)
	return self._hasMic, self._hasSpeaker
end

function ClassRef:joinTeamRoom(memberId)
	if not memberId or (memberId and memberId == self._memberId) then
		local teamId = app:sendMsg("TeamModel", "getTeamId")
		self:updateTeam(teamId)
	end
end

function ClassRef:openMic(isOpen)
	if self._hasMic ~= isOpen then
		self._model:setModeRealTime()
		if isOpen then
			local code = im.openMic()
			if code == 0 then
				self._hasMic = isOpen	
				EM:notify("updateMicAndSpeakBtnState", {type = "mic", open = true})	
			end
		else
			local code = im.closeMic()
			if code == 0 then
				self._hasMic = isOpen
				EM:notify("updateMicAndSpeakBtnState", {type = "mic", open = false})
			end
		end
	end
end

function ClassRef:openSpeaker(isOpen)
	if self._hasSpeaker ~= isOpen then
		self._model:setModeRealTime()
		if isOpen then
			local code = im.openSpeaker()
			if code == 0 then
				self._hasSpeaker = isOpen
				EM:notify("updateMicAndSpeakBtnState", {type = "speaker", open = true})
			end
		else
			local code = im.closeSpeaker()
			if code == 0 then
				self._hasSpeaker = isOpen
				EM:notify("updateMicAndSpeakBtnState", {type = "speaker", open = false})	
			end
		end
	end
end

function ClassRef:needBackToRealtime()
	local need = self:hasMicOrSpeaker()
	-- print("===>IMAPI IMRecordController.needBackToRealtime", need, self._roomId, self._hasMic, self._hasSpeaker)
	if need then
		self._model:setModeRealTime()
		if self._hasMic then
			im.openMic()
		end
		if self._hasSpeaker then
			im.openSpeaker()
		end
	end
	return need
end

----------------------------------------------------------------
function ClassRef:onPlayEnd(succ, filePath)
	im.isPlaying = false
	-- AM.resumeAll()
	self:_setVoiceBtn(nil)
end

function ClassRef:onJoinRoom(succ, room, memberId)
	if succ then
		self._roomId = room
		self._memberId = memberId

		self._model:setModeRealTime()
		-- print("===>IMAPI IMRecordController onJoinRoom", self._hasMic, self._hasSpeaker)
		if self._hasMic then
			im.openMic()
		end
		if self._hasSpeaker then
			im.openSpeaker()
		end
	else
		self._roomId = nil
		self._memberId = nil
	end
end

function ClassRef:onQuitRoom(succ, room)
	self._roomId = nil
	self._memberId = nil
	self._model:setModeTranslate()
end

function ClassRef:onMemberVoice(memgerIds, status)
	
end

-- 进入队伍／退出队伍
function ClassRef:updateTeam(teamId)
	-- print("===>IMAPI IMRecordController.updateTeam teamId", teamId)
	if teamId then
		self._model:setModeRealTime()
		local code = im.joinTeamRoom(tostring(teamId))
		if code ~= 0 then
			self._roomId = nil
			self._memberId = nil
		end
	else
		if self._roomId then
			self._model:setModeRealTime()
			if self._hasMic then
				im.closeMic()
			end
			if self._hasSpeaker then
				im.closeSpeaker()
			end
			im.quitRoom(self._roomId)
		end
	end
end

-------------------------------- record audio -------------------------------
function ClassRef:_initRecordNode()
	if self._recordNode then
		self._recordNode:findChild("Panel/voiceWarning_1"):setVisible(false)
		for i = 0, RECORD_COUNTDOWN do
			local timeNode = self._recordNode:findChild("Panel/num_"..i)
			timeNode:setVisible(false)
		end
		self._recordNode:findChild("Panel/img_gth"):setVisible(false)
	end
end

function ClassRef:_showStartRecording()
	if nil == self._recordNode then
		self._recordNode = cc.CSLoader:createNode(Res.IMRecordeStartNode)
		self._recordNode:setAnchorPoint(cc.p(1,0.5))
		self._recordNode:setPosition(cc.p(display.width / 2,display.height / 2))
		self:addChild(self._recordNode)
	end
	self:_initRecordNode()
	self._recordNode:setVisible(true)
	self._recordNode:findChild("Panel/voiceWarning_1"):setVisible(true)
	self._recordNode:findChild("Panel/Text"):setString(L("IMRecordCancel"))
	self._recordNode:getTimeline():gotoFrameAndPlay(0, true)
	if self._recordStopNode then self._recordStopNode:setVisible(false) end
end
function ClassRef:_showStopRecording()
	if nil == self._recordStopNode then
		self._recordStopNode = cc.CSLoader:createNode(Res.IMRecordeStopNode)
		self._recordStopNode:setAnchorPoint(cc.p(1,0.5))
		self._recordStopNode:setPosition(cc.p(display.width / 2,display.height / 2))
		self:addChild(self._recordStopNode)
	end
	if self._recordNode then self._recordNode:setVisible(false) end
	self._recordStopNode:setVisible(true)
end

function ClassRef:_hideRecordNodes()
	if self._recordNode then 
		self._recordNode:setVisible(false) 
		self._recordNode:getTimeline():pause()
	end
	if self._recordStopNode then self._recordStopNode:setVisible(false) end
end

function ClassRef:_showRecordingCountDown(time)
	-- 显示语音录制倒计时
	if self._recordNode then
		self._recordNode:getTimeline():gotoFrameAndPause(0)
		self:_initRecordNode()
		self._recordNode:findChild("Panel/num_"..time):setVisible(true)
		self._recordNode:findChild("Panel/Text"):setString(L("IMRecordCancel"))
	end
	if self._recordStopNode then self._recordStopNode:setVisible(false) end
end

function ClassRef:_showRecordingTimeout()
	-- 显示语音录制时间过长提示
	if self._recordNode then
		self._recordNode:getTimeline():gotoFrameAndPause(0)
		self:_initRecordNode()
		self._recordNode:findChild("Panel/img_gth"):setVisible(true)
		self._recordNode:findChild("Panel/Text"):setString(L("IMRecordTimeOut"))
	end
	if self._recordStopNode then self._recordStopNode:setVisible(false) end
end

-------------------------------------------------------------
-- phase  	状态
-- channel  聊天频道(phase=start有此参数)
-- endCb 	record结束回调(phase=start有此参数)
-- 
-- channel = nil 	没有聊天频道，通过endCb处理record结果
-- channel ~= nil 	是IM聊天，直接发送到相应频道（"current"， 表示当前频道）
function ClassRef:_setRecordPhase(phase, channel, endCb)
	if self._recordPhase == phase then return end 

	-- print("===>IMAPI IM._setRecordPhase", self._recordPhase, phase)

	if phase == Enums.IMRecordPhase.Start then
		AM.pauseAll()
		self._recordChannel = channel
		self._recordEndCb = endCb
		self._recordStartTime = app:getTime()
	elseif phase == Enums.IMRecordPhase.Record then
		self:_showStartRecording()
	elseif phase == Enums.IMRecordPhase.Cancel then
		self:_showStopRecording()
	elseif phase == Enums.IMRecordPhase.End then
		AM.resumeAll()
		self:_hideRecordNodes()
	end

	local prevPhase = self._recordPhase
	self._recordPhase = phase

	if prevPhase == Enums.IMRecordPhase.End then
		if Enums.IMRecordPhase.Start == phase then
			self:startRecord()
		elseif Enums.IMRecordPhase.Record == phase then
			self._recordPhase = Enums.IMRecordPhase.Cancel
			self:_hideRecordNodes()
			display.pushToast(L("tips_3000140"))
			self:stopRecord()
		end
	elseif prevPhase == Enums.IMRecordPhase.Start then
		if Enums.IMRecordPhase.End == phase then
			self:stopRecord()
		end
	elseif prevPhase == Enums.IMRecordPhase.Record then
		if Enums.IMRecordPhase.End == phase then
			local duration = app:getTime() - self._recordStartTime
			-- print("===>IMAPI IMRecordController end duration", duration)
			if duration > 1 then
				self:stopRecord(math.min(duration, RECORD_DURATION_MAX))
			else
				self:stopRecord()
				display.pushToast(L("tips_3000140"))
			end
		end
	elseif prevPhase == Enums.IMRecordPhase.Cancel then
		if Enums.IMRecordPhase.End == phase then
			self:stopRecord()
		end
	end
end

function ClassRef:removeScheduler()
	if self._cronsIdx then
		scheduler.cancelCron(self._cronsIdx)
		self._cronsIdx = nil
	end
end

function ClassRef:_tick(dt)
	-- 录音时长超过20s直接结束
	if self._recordStartTime ~= 0 and self._recordPhase == Enums.IMRecordPhase.Record then
		local duration = app:getTime() - self._recordStartTime
		local remainTime = math.ceil(RECORD_DURATION_MAX - duration)
		if remainTime > 0 and remainTime <= RECORD_COUNTDOWN + 1 then
			self:_showRecordingCountDown(remainTime-1)
		elseif remainTime == 0 then
			self:_showRecordingTimeout()
		elseif remainTime < 0 then
			AM.resumeAll()
			self:_hideRecordNodes()
			self:stopRecord(math.min(duration, RECORD_DURATION_MAX))
		end
	end
end

return ClassRef